#include "USB.h"

#include <guiddef.h>
#include <initguid.h>
#include <WINDOWS.H>
#include <setupapi.h>

#pragma comment(lib, "Setupapi.lib")

DEFINE_GUID(GUID_DEVINTERFACE_HUBCONTROLLER, 0x3abf6f2dL, 0x71c4, 0x462a, 0x8a, 0x92, 0x1e, 0x68, 0x61, 0xe6, 0xaf, 0x27);
#define BUFFER_SIZE 2048

USB::USB(void)
{
	
}

USB::~USB(void)
{
	FreeHostControllers();
}

const std::vector<USBController*>* USB::GetHostControllers()
{
	FreeHostControllers();

	HDEVINFO hDevInfo = SetupDiGetClassDevs(&GUID_DEVINTERFACE_HUBCONTROLLER, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
	if (hDevInfo != INVALID_HANDLE_VALUE)
	{
		BYTE *buffer = new BYTE[BUFFER_SIZE];
		if (buffer)
		{
			BOOL success;
			int i = 0;

			do 
			{
				USBController *pHost = new USBController();
				pHost->SetIndex(i);

				SP_DEVICE_INTERFACE_DATA sdid;
				sdid.cbSize = sizeof(sdid);

				success = SetupDiEnumDeviceInterfaces(hDevInfo, NULL, &GUID_DEVINTERFACE_HUBCONTROLLER, i, &sdid);
				if (success)
				{
					SP_DEVINFO_DATA sdd;
					memset(&sdd, 0, sizeof(sdd));
					sdd.cbSize = sizeof(sdd);

					SP_DEVICE_INTERFACE_DETAIL_DATA *pSdidd = (SP_DEVICE_INTERFACE_DETAIL_DATA*)buffer;
					pSdidd->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);

					DWORD requiredSize = 0;
					DWORD bufferSize = BUFFER_SIZE;
					if (SetupDiGetDeviceInterfaceDetail(hDevInfo, &sdid, pSdidd, bufferSize, &requiredSize, &sdd))
					{
						pHost->SetDevicePath(pSdidd->DevicePath);

						DWORD requiredSize2;
						DWORD regType;
						if (SetupDiGetDeviceRegistryProperty(hDevInfo, &sdd, SPDRP_DEVICEDESC, &regType, buffer, BUFFER_SIZE, &requiredSize2))
						{
							pHost->SetDeviceDescription((wchar_t*)buffer);
						}
						if (SetupDiGetDeviceRegistryProperty(hDevInfo, &sdd, SPDRP_DRIVER, &regType, buffer, BUFFER_SIZE, &requiredSize2))
						{
							pHost->SetDriverKeyName((wchar_t*)buffer);
						}
					}

					m_hostControllers.push_back(pHost);
				}

				++i;
			} while (success);

			delete [] buffer;
		}

		SetupDiDestroyDeviceInfoList(hDevInfo);
	}

	return &m_hostControllers;
}

void USB::FreeHostControllers()
{
	for (std::vector<USBController*>::iterator	iter = m_hostControllers.begin();
		iter != m_hostControllers.end();
		++iter)
	{
		USBController *pUSBController = (USBController*)*iter;
		delete pUSBController;
	}

	m_hostControllers.clear();
}